package com.gzsxy.esjy.service.netty.service;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.gzsxy.esjy.common.Assert;
import com.gzsxy.esjy.service.netty.common.transactional.annotations.GosunTransactional;
import com.gzsxy.esjy.service.netty.dao.ResourcesIndexDao;
import com.gzsxy.esjy.service.netty.decoder.FilePathParser;
import com.gzsxy.esjy.service.netty.dto.ExpiredResourceDto;
import com.gzsxy.esjy.service.netty.dto.UploadDto;
import com.gzsxy.esjy.service.netty.entity.ResourcesIndex;

import com.gzsxy.esjy.service.netty.fileServer.configure.ServerStaticProperties;
import com.gzsxy.esjy.service.netty.util.FileUtils;
import com.gzsxy.esjy.util.ReflectUtil;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.multipart.FileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;


/**
 * 文件上传处理
 * @author zhangxiaolong
 * @date 2022/7/11 9:36
 */
@Service
public class FileUploadService {

    private final static Logger log = LoggerFactory.getLogger(FileUploadService.class);

    @Autowired
    private ResourcesIndexDao resourcesIndexDao;

    /**
     * 文件上传
     *
     * @param dto
     * @return
     * @throws Exception
     */
    @GosunTransactional(lock = false, transactional = true)
    public ResourcesIndex saveFile(UploadDto dto) throws Exception {
        String content = dto.getContent();
        String fileType = dto.getFileType();
        if (fileType.startsWith(".")) {
            fileType = fileType.substring(1);
        }
        int b = content.indexOf("base64,");
        if (b >= 0) {
            content = content.substring(b + "base64,".length());
        }
//        byte[] decode = Base64Util.decode(content);
        //兼容某些不是java8的Base64编码
        byte[] decode = Base64.getMimeDecoder().decode(content);
        ResourcesIndex index = new ResourcesIndex();
        String name = UUID.randomUUID().toString();
        String fileName = null;
        if (!StringUtils.isEmpty(dto.getIndex())) {
            fileName = dto.getIndex();
            if (fileName.startsWith(ServerStaticProperties.THIS_SYSTEM + "/")) {
                fileName = fileName.replace(ServerStaticProperties.THIS_SYSTEM + "/", "");
            }
            name = fileName;
        } else {
            fileName = name + "." + fileType;
        }
        String filePath = FileUtils.getFilePath(dto.getBaseDir(), fileName);
        index.setId(name);
        index.setFileName(StringUtils.isEmpty(dto.getFileName()) ? fileName : dto.getFileName());
        index.setFileSize((long) decode.length);
        index.setFilePath(filePath);
        index.setFileIndex(ServerStaticProperties.THIS_SYSTEM + "/" + fileName);
        index.setSystemId(ServerStaticProperties.THIS_SYSTEM);
        int day = dto.getExpired();
        //过期天数
        if (day > 0) {
            long date = System.currentTimeMillis() + dto.getExpired() * 24 * 60 * 60 * 1000;
            index.setExpiredTime(date);
        } else {
            index.setExpiredTime(0L);
        }
        ResourcesIndex resourcesIndex = resourcesIndexDao.selectById(name);
        if (resourcesIndex != null) {
            ReflectUtil.editBeanfromBean(index, resourcesIndex);
            resourcesIndexDao.updateById(resourcesIndex);
        } else {
            resourcesIndexDao.insert(index);
        }
        String fullPath = FileUtils.createFileOfByte(decode, ServerStaticProperties.RESOURCES_ROOT + filePath);
        log.info("文件上传成功 {}", fullPath);
        return index;
    }


    /**
     * 创建新图片
     *
     * @param filePath
     * @param resourcesRoot
     * @param directIndex
     * @param oriDirectIndex
     * @return
     * @throws IOException
     * @throws NumberFormatException
     */
    @GosunTransactional(lock = true, transactional = true, key = "{#directIndex}")
    public String createnewPhoto(FilePathParser filePath, String resourcesRoot, String directIndex, String oriDirectIndex) throws NumberFormatException, IOException {
        String path = resourcesRoot + directIndex;
        File file = new File(path);
        if (!file.exists()) {
            String oriPath = resourcesRoot + oriDirectIndex;
            file = new File(oriPath);
            Assert.notTrue(file.exists() && !file.isHidden() && !file.isDirectory() && file.isFile(), String.format("file[%s] not found", directIndex), HttpResponseStatus.NOT_FOUND.code());
            String param2 = filePath.getParam2();
            String param1 = filePath.getParam1();
//			if(param2 != null) {
//				Thumbnails.of(file).size(Integer.parseInt(param1), Integer.parseInt(param2)).toFile(path);
//				return path ;
//			}
//			Thumbnails.of(file).scale(Double.parseDouble(param1)/100.0).toFile(path);
//			deleteFile(filePath.getSystemId(), filePath.getDirectIndex(),UUID.randomUUID().toString()+"_thumbnail", 1);
        }
        return path;
    }


    /**
     * 更新文件过期时间
     *
     * @param index 文件索引
     * @param day 时间/天 0代表永不过期
     */
    @GosunTransactional(lock = true, transactional = true, key = "{#index}")
    public void updateExpiredTime(String index, int day) {
        LambdaQueryWrapper<ResourcesIndex> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ResourcesIndex::getFileIndex,index);
        ResourcesIndex rsourceIndex = resourcesIndexDao.selectOne(wrapper);
        if(rsourceIndex != null) {
            long date = 0;
            if (day != 0) {
                date = System.currentTimeMillis() + day * 24 * 60 * 60 * 1000;
            }
            rsourceIndex.setExpiredTime(date);
            resourcesIndexDao.updateById(rsourceIndex);
        }
    }


    /**
     * 文件上传
     *
     * @param file
     * @param expired
     * @return
     * @throws IOException
     */
    @GosunTransactional(lock = false, transactional = true)
    public ResourcesIndex saveFile(String fileIndex, FileUpload file, Integer expired) throws IOException {
        ResourcesIndex index = new ResourcesIndex();
        String name = UUID.randomUUID().toString();
        String fileName = null;
        //是否为修改文件
        if (!StringUtils.isEmpty(fileIndex)) {
            fileName = fileIndex;
            if (fileName.startsWith(ServerStaticProperties.THIS_SYSTEM + "/")) {
                fileName = fileName.replace(ServerStaticProperties.THIS_SYSTEM + "/", "");
            }
            name = fileName;
        } else {
            String filename = file.getFilename();
            int lastIndex = filename.lastIndexOf(".");
            String fileType = filename.substring(lastIndex + 1);
            fileName = name + "." + fileType;
        }
        String filePath = FileUtils.getFilePath(null, fileName);
        index.setId(name);
        index.setFileName(file.getFilename());
        index.setFileSize(file.length());
        index.setFilePath(filePath);
        index.setFileIndex(ServerStaticProperties.THIS_SYSTEM + "/" + fileName);
        index.setSystemId(ServerStaticProperties.THIS_SYSTEM);
        //过期时间按天算
        if (expired != null && expired > 0) {
            long date = System.currentTimeMillis() + expired * 24 * 60 * 60 * 1000;
            index.setExpiredTime(date);
        } else {
            index.setExpiredTime(0L);
        }
        ResourcesIndex resourcesIndex = resourcesIndexDao.selectById(name);
        if (resourcesIndex != null) {
            ReflectUtil.editBeanfromBean(index, resourcesIndex);
            resourcesIndexDao.updateById(resourcesIndex);
        } else {
            resourcesIndexDao.insert(index);
        }
        file.renameTo(new File(ServerStaticProperties.RESOURCES_ROOT + filePath));
        log.info("文件上传成功 {}", ServerStaticProperties.RESOURCES_ROOT + filePath);
        return index;
    }

    /**
     * 批量设置过期文件
     */
    @GosunTransactional(lock = false, transactional = true)
    public void updateFileByList(List<ExpiredResourceDto> lists) {
        lists.forEach(l -> {
            updateExpiredTime(l.getIndex(), l.getExpried());
        });
    }

    public List<ResourcesIndex> getFileListByPath(String path) {
        ArrayList<ResourcesIndex> list = new ArrayList<>();
        File file = Paths.get(ServerStaticProperties.RESOURCES_ROOT, path).toFile();
        if (!file.exists()) {
            return list;
        }
        File[] files = file.listFiles();
        if (null == files){
            return list;
        }
        for (File f : files) {
            if (f.isDirectory()){
                continue;
            }
            ResourcesIndex index = new ResourcesIndex();
            index.setFileSize(f.length());
            index.setFileName(f.getName());
            index.setFilePath(f.getAbsolutePath());
            index.setFileIndex(Paths.get(ServerStaticProperties.ABSOLUTE_RESOURCES_PREFIX, ServerStaticProperties.THIS_SYSTEM,path, f.getName()).toString());
            list.add(index);
        }

        return list;
    }

    /**
     * 根据fileIndex查询文件详情
     * @param fileIndex
     * @return
     */
    public ResourcesIndex getDetailByIndex(String fileIndex){
        LambdaQueryWrapper<ResourcesIndex> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ResourcesIndex::getFileIndex,fileIndex);
        ResourcesIndex rsourceIndex = resourcesIndexDao.selectOne(wrapper);
        return rsourceIndex;
    }


    /**
     * 定时删除过期文件
     */
    public void deleteFiles(){
        LambdaQueryWrapper<ResourcesIndex> wrapper = Wrappers.lambdaQuery();
        wrapper.ne(ResourcesIndex::getExpiredTime,0)
                .le(ResourcesIndex::getExpiredTime,System.currentTimeMillis())
                .eq(ResourcesIndex::getSystemId, ServerStaticProperties.THIS_SYSTEM);
        List<ResourcesIndex> list = resourcesIndexDao.selectList(wrapper);
        log.info("过期文件数据量【】",list.size());
        if(!CollectionUtils.isEmpty(list)) {
            list.stream().map(s ->{
                String filePath = ServerStaticProperties.RESOURCES_ROOT+s.getFilePath();
                try {
                    FileUtils.deleteFile(filePath) ;
                    resourcesIndexDao.deleteById(s);
                }catch(Exception e) {
                    log.warn("文件{}删除失败", filePath);
                    log.error(e.getMessage(), e);
                }
                return s;
            }).collect(Collectors.toList());
        }
    }
}
